{"componentChunkName":"component---node-modules-gatsby-theme-chronoblog-src-templates-post-js","path":"/2021-12-25-nodejs-postgresql-server-digitalocean/","result":{"data":{"mdx":{"id":"997da485-c273-5f0a-913c-679e25e9e0ff","excerpt":"Using Docker, let's spin up a Node.js app and Postgresql DB containers and deploy them on the Droplet we created in the last  post . Install…","frontmatter":{"title":"Setting up a with Node.js App and Postgresql Database on DigitalOcean Droplet","date":"2021-12-25T00:00:00.000Z","description":"We will spin up a Node.js app with Postgresql DB on DigitalOcean Droplet","tags":["Node.js","Postgresql","DigitalOcean","Droplet","Docker","Docker Compose"],"cover":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAQFCP/EABcBAAMBAAAAAAAAAAAAAAAAAAABAgP/2gAMAwEAAhADEAAAAed4cpmr0Cj/xAAZEAADAQEBAAAAAAAAAAAAAAACAwQBBRD/2gAIAQEAAQUCm5GUJZGIjRNiC9//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAYEQEAAwEAAAAAAAAAAAAAAAABAAIRQf/aAAgBAgEBPwELa6wHrP/EACQQAAECAgsBAAAAAAAAAAAAAAIBEQATAwQSFCAhIiMyUWHw/9oACAEBAAY/Aq0d7oRkBbYl5eJ91C7g6RdfYRJgk6Plg//EABwQAQABBAMAAAAAAAAAAAAAAAERACAhoTFBUf/aAAgBAQABPyEN9HRcpo36pkJhyTJXjVYWkk7P/9oADAMBAAIAAwAAABB43//EABcRAQEBAQAAAAAAAAAAAAAAAAEAEUH/2gAIAQMBAT8QB11get//xAAZEQEAAwEBAAAAAAAAAAAAAAABABExIaH/2gAIAQIBAT8QE1o4VnPb2AKsZ//EABwQAQEBAAIDAQAAAAAAAAAAAAERIUFxACAxYf/aAAgBAQABPxAd/Br5By2R5epDnzqNAC5DX6OXxXsihCqR37l6T0//2Q==","aspectRatio":2,"src":"/static/32e55ca0c3f225cabc1b8a9fe6cdc719/3e61c/cover.jpg","srcSet":"/static/32e55ca0c3f225cabc1b8a9fe6cdc719/7fcb3/cover.jpg 192w,\n/static/32e55ca0c3f225cabc1b8a9fe6cdc719/42594/cover.jpg 384w,\n/static/32e55ca0c3f225cabc1b8a9fe6cdc719/3e61c/cover.jpg 768w,\n/static/32e55ca0c3f225cabc1b8a9fe6cdc719/0a363/cover.jpg 1152w,\n/static/32e55ca0c3f225cabc1b8a9fe6cdc719/271d8/cover.jpg 1280w","srcWebp":"/static/32e55ca0c3f225cabc1b8a9fe6cdc719/dd090/cover.webp","srcSetWebp":"/static/32e55ca0c3f225cabc1b8a9fe6cdc719/ae504/cover.webp 192w,\n/static/32e55ca0c3f225cabc1b8a9fe6cdc719/fef30/cover.webp 384w,\n/static/32e55ca0c3f225cabc1b8a9fe6cdc719/dd090/cover.webp 768w,\n/static/32e55ca0c3f225cabc1b8a9fe6cdc719/44170/cover.webp 1152w,\n/static/32e55ca0c3f225cabc1b8a9fe6cdc719/e170b/cover.webp 1280w","sizes":"(max-width: 768px) 100vw, 768px","presentationWidth":768,"presentationHeight":384},"resize":{"src":"/static/32e55ca0c3f225cabc1b8a9fe6cdc719/3e61c/cover.jpg"}}}},"fields":{"slug":"/2021-12-25-nodejs-postgresql-server-digitalocean/"},"body":"var _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Setting up a with Node.js App and Postgresql Database on DigitalOcean Droplet\",\n  \"cover\": \"./cover.jpg\",\n  \"date\": \"2021-12-25T00:00:00.000Z\",\n  \"description\": \"We will spin up a Node.js app with Postgresql DB on DigitalOcean Droplet\",\n  \"tags\": [\"Node.js\", \"Postgresql\", \"DigitalOcean\", \"Droplet\", \"Docker\", \"Docker Compose\"]\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"Using Docker, let's spin up a Node.js app and Postgresql DB containers and deploy them on the Droplet we created in the last \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/2021-12-24-digitalocean-droplet/\"\n  }, \"post\"), \".\"), mdx(\"h3\", {\n    \"id\": \"install-docker\"\n  }, \"Install Docker\"), mdx(\"p\", null, \"Connect to the Droplet via SSH or PuTTy and follow the instructions on the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.docker.com/engine/install/ubuntu/\"\n  }, \"Docker\"), \" and \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.docker.com/compose/install/\"\n  }, \"Docker Compose\"), \" documentation pages to install Docker and Docker Compose on Ubuntu.\"), mdx(\"h3\", {\n    \"id\": \"dockerfile\"\n  }, \"Dockerfile\"), mdx(\"p\", null, \"Let's create a Dockerfile to install Node.js. We will also specify all files (code, configs, assets, etc) to copy into the container, which we will generate in a moment.\"), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"Dockerfile\")), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\"\n  }, \"FROM node:latest\\nWORKDIR /app\\nCOPY package.json .\\nRUN npm install\\nCOPY . .\\nRUN npx prisma generate\\nEXPOSE 4000\\nCMD [\\\"npm\\\", \\\"run\\\", \\\"start\\\"]\\n\")), mdx(\"p\", null, \"If we are using \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.prisma.io/\"\n  }, \"Prisma\"), \" in our app, we should also let Docker run the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"prisma generate\"), \" command during build.\"), mdx(\"h3\", {\n    \"id\": \"dockerignore\"\n  }, \".dockerignore\"), mdx(\"p\", null, \"Before we continue, let's create a .dockerignore file to exclude certain files when Docker runs the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Copy\"), \" command in the Dockerfile we created earlier.\"), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"dockerignore\")), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\"\n  }, \"node_modules\\nDockerfile\\n.env\\n.dockerignore\\n.git\\n.gitignore\\n\")), mdx(\"h3\", {\n    \"id\": \"docker-composeyml\"\n  }, \"docker-compose.yml\"), mdx(\"p\", null, \"We will create three different docker-compose.yml files to configure our application's dependencies in development and production environment.\"), mdx(\"p\", null, \"Let's start with the main docker-compose file, which includes the configuration for our Node app as well as for the Postgresql image we will use from \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://hub.docker.com/_/postgres\"\n  }, \"DockerHub\"), \".\"), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"docker-compose.yml\")), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\"\n  }, \"version: '3'\\nservices:\\n  node-app:\\n    build: .\\n    volumes:\\n      - ./:/app\\n      - /app/node_modules\\n    environment:\\n      - PORT=4000\\n    depends_on:\\n      - db\\n  db:\\n    image: postgres\\n    restart: always\\n    environment:\\n      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}\\n      - POSTGRES_USER=${POSTGRES_USER}\\n    volumes:\\n      - postgres:/var/lib/postgresql/data\\nvolumes:\\n  postgres:\\n\")), mdx(\"p\", null, \"Next, we will create \", mdx(\"em\", {\n    parentName: \"p\"\n  }, \"docker-compose.dev.yml\"), \" and \", mdx(\"em\", {\n    parentName: \"p\"\n  }, \"docker-compose.prod.yml\"), \" to configure the development and production environment, respectively\"), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"docker-compose.dev.yml\")), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\"\n  }, \"version: '3'\\nservices:\\n  node-app:\\n    environment:\\n      - NODE_ENV=development\\n      - DATABASE_URL=${DATABASE_URL_DEV}\\n    command: npm run start\\n\")), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"docker-compose.prod.yml\")), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\"\n  }, \"version: '3'\\nservices:\\n  node-app:\\n    environment:\\n      - NODE_ENV=production\\n      - DATABASE_URL=${DATABASE_URL_DIGITALOCEAN}\\n    command: >\\n      sh -c \\\"npm run db:migrate:prod &&\\n             npm run build &&\\n             npm run start:prod\\\"\\n\")), mdx(\"h3\", {\n    \"id\": \"build-images-create-and-start-containers\"\n  }, \"Build Images, Create and Start Containers\"), mdx(\"p\", null, \"We can use the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"docker-compose up\"), \" command to build images and create containers, then start them all at once. We can also specify .env file with the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"--env-file\"), \" flag, followed by the path to the .env file.\"), mdx(\"p\", null, \"To do this for a development environment, we run the following:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\"\n  }, \"docker-compose -f docker-compose.yml -f docker-compose.dev.yml --env-file ./.env up -d\\n\")), mdx(\"p\", null, \"Or the following for a production environment:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\"\n  }, \"docker-compose -f docker-compose.yml -f docker-compose.prod.yml --env-file ./.env up -d\\n\")), mdx(\"p\", null, \"We should now have two containers running for our Node app and Postgresql DB.\"), mdx(\"span\", {\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"820px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"7.3170731707317085%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/jpeg;base64,/9j/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wgARCAABABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAQGB//EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHIqYJBC//EABgQAAIDAAAAAAAAAAAAAAAAAAIDMTIz/9oACAEBAAEFAmanLLf/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAWEAADAAAAAAAAAAAAAAAAAAABEIH/2gAIAQEABj8CNf8A/8QAGRAAAQUAAAAAAAAAAAAAAAAAAAGBobHw/9oACAEBAAE/IZQy6lR//9oADAMBAAIAAwAAABAHz//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAEDAQE/ECf/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAWEAEBAQAAAAAAAAAAAAAAAAAAsQH/2gAIAQEAAT8QPpqif//Z')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"containers running\",\n    \"title\": \"containers running\",\n    \"src\": \"/static/b13a9b5c3970ac838a564f49eaecf4ce/63a81/docker-ps.jpg\",\n    \"srcSet\": [\"/static/b13a9b5c3970ac838a564f49eaecf4ce/bd2b6/docker-ps.jpg 205w\", \"/static/b13a9b5c3970ac838a564f49eaecf4ce/ceeba/docker-ps.jpg 410w\", \"/static/b13a9b5c3970ac838a564f49eaecf4ce/63a81/docker-ps.jpg 820w\", \"/static/b13a9b5c3970ac838a564f49eaecf4ce/f25e0/docker-ps.jpg 954w\"],\n    \"sizes\": \"(max-width: 820px) 100vw, 820px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  }), \"\\n    \"), mdx(\"h3\", {\n    \"id\": \"conclusion\"\n  }, \"Conclusion\"), mdx(\"p\", null, \"We have deployed a Node app and Postgresql DB to our Droplet with Docker and they are running on the Docker containers we created.\"), mdx(\"p\", null, \"In the next post, we will add Nginx Web Server to our Droplet to direct traffic to our server via reverse-proxy.\"));\n}\n;\nMDXContent.isMDXComponent = true;"}},"pageContext":{"id":"997da485-c273-5f0a-913c-679e25e9e0ff"}},"staticQueryHashes":["1961101537","2542493696"]}